package SGEngine

import (
	//"fmt"
	"github.com/gl"
)

var (
	ACProgramMgr aCProgramMgr_
)

const (
	PROGRAM_QUAD = 1
	PROGRAM_IMG  = 2
)

type aCProgramMgr_ struct {
	Programs map[uint16]*Program
}

func init() {
	ACProgramMgr.Programs = make(map[uint16]*Program)
}

const (
	vShaderStr string = `
      attribute vec4 vPosition; 
      void main() 
      {
      	gl_Position = gl_ModelViewProjectionMatrix*vPosition;
      }
	`
	fShaderStr string = `
      uniform vec4 inColor;
      void main() 
      {
      	gl_FragColor = inColor;
      }
	`
	/////////////////////////////////////////
	vImageShaderStr string = `
	  attribute vec4 vPosition;
	  attribute vec2 a_texCoord;
	  varying vec2 v_texCoord;
      void main() 
      {
      	gl_Position = gl_ModelViewProjectionMatrix*vPosition;
      	v_texCoord = a_texCoord;
      }
    `
	fImageShaderStr string = `
	 uniform vec4 inColor;
     uniform sampler2D s_texture;
     varying vec2 v_texCoord;
      void main() 
      { 
      	gl_FragColor =inColor*texture2D(s_texture, v_texCoord);
      }
	`
)

type Program struct {
	VShader       gl.Shader
	fShader       gl.Shader
	ProgramObject gl.Program
}

func (c *aCProgramMgr_) GetProgram(ptype uint16) *Program {
	if v, ok := c.Programs[ptype]; ok == true {

		return v
	}

	var Rp *Program
	switch ptype {
	case PROGRAM_QUAD:
		Rp = NewProgram(vShaderStr, fShaderStr)
	case PROGRAM_IMG:
		Rp = NewProgram(vImageShaderStr, fImageShaderStr)
	}
	c.Programs[ptype] = Rp
	return Rp
}

func NewProgram(Vstr, Fstr string) *Program {
	RProgram := new(Program)

	RProgram.VShader = gl.CreateShader(gl.VERTEX_SHADER)
	RProgram.fShader = gl.CreateShader(gl.FRAGMENT_SHADER)
	RProgram.VShader.Source(Vstr)
	RProgram.fShader.Source(Fstr)
	RProgram.VShader.Compile()
	RProgram.fShader.Compile()

	//	fmt.Println(RProgram.VShader.GetInfoLog())
	//	fmt.Println(RProgram.fShader.GetInfoLog())

	RProgram.ProgramObject = gl.CreateProgram()
	RProgram.ProgramObject.AttachShader(RProgram.fShader)
	RProgram.ProgramObject.AttachShader(RProgram.VShader)
	//RProgram.ProgramObject.BindAttribLocation(0, "vPosition")
	RProgram.ProgramObject.Link()
	//RProgram.ProgramObject.Use()

	return RProgram
}
